package graph.net.commands;


import graph.net.internal.ServiceLocator;
import graph.net.internal.ServiceName;
import graph.service.GraphService;

import java.util.ArrayList;
import java.util.List;



/********************************************************************
 * @author amahmood 
 * Parses incoming message. Tokenize it in command and
 * parameters. And executes the command.
 * 
 *******************************************************************/
public class CommandProcessor
{

    CommandName commands;
    private static final String PRAM_START_MARKER = "\\(";
    private static final String PRAM_END_MARKER = ")";
    private static final String PRAM_SEPARATOR = ",";
    private ServiceLocator serviceLocator = null;

    /********************************************************************
     * 
     *******************************************************************/
    public CommandProcessor(ServiceLocator serviceLocator)
    {
        this.serviceLocator = serviceLocator;

        serviceLocator.putService(ServiceName.GraphService, new GraphService());
    }

    /********************************************************************
     * @param message
     * @return String[]
     * @throws InvalidCommandFormatException
     *******************************************************************/
    private String[] parseMessage(String message) throws InvalidCommandFormatException
    {

        if (message == null)
            throw new IllegalArgumentException("One of the requried parameter is null.");

        List<String> result = new ArrayList<String>();

        String[] commandTokens = message.split(PRAM_START_MARKER);

        if (commandTokens != null && commandTokens.length > 0)
        {
            result.add(commandTokens[0].trim());

            if (commandTokens.length == 2)
            {
                String strPrams = commandTokens[1].replace(PRAM_END_MARKER, " ");
                String[] prams = strPrams.split(PRAM_SEPARATOR);

                if (prams != null && prams.length > 0)
                {
                    for (int i = 0; i < prams.length; i++)
                        result.add(prams[i].trim());
                }
                else throw new InvalidCommandFormatException(
                        "Invalid command format. Please send Help(command name) to learn correct syntex");
            }
        }
        else throw new InvalidCommandFormatException(
                "Invalid command format. Please send Help(command name) to learn correct syntex");

        String[] out = new String[result.size()];

        result.toArray(out);

        return out;
    }

    /********************************************************************
     * @param message
     * @return
     * @throws InvalidCommandFormatException
     * @throws InvalidCommandException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     *******************************************************************/
    public String processCommand(String message) throws InvalidCommandFormatException, InvalidCommandException,
            IllegalArgumentException, UnsupportedOperationException
    {
        String response = "";

        if (message != null && message.length() > 0)
        {
            String[] messageTokens = parseMessage(message);

            CommandName commandId;
            try
            {
                commandId = CommandName.valueOf(messageTokens[0].toLowerCase());
            }
            catch (Exception e)
            {
                throw new InvalidCommandException("Unknown command "+message+ ". Please send Help message to get list of commands.");
            }

            ICommand command = CommandFactory.createCommand(commandId, serviceLocator);

            response = command.execute(messageTokens);
        }

        return response;
    }
}
